package ru.sgu.codecenter.fidx.command;

import ru.sgu.codecenter.fidx.model.HelpItem;

import java.util.ArrayList;
import java.util.List;

public class HelpCommand extends Command {
    @Override
    public String getName() {
        return "help";
    }

    @Override
    public void execute(String[] args) {
        if (args.length == 1 && args[0].equalsIgnoreCase("--syntax")) {
            System.out.print("FIDX is based on Apache Lucene Seach Engine. You can use Lucene query syntax:\n\n");

            System.out.print(
                "\tWildcard Searches\n" +
                "Lucene supports single and multiple character wildcard searches within single terms (not within phrase queries).\n" +
                "To perform a single character wildcard search use the \"?\" symbol.\n" +
                "To perform a multiple character wildcard search use the \"*\" symbol.\n\n" +

                "\tFuzzy Searches\n" +
                "Lucene supports fuzzy searches based on the Levenshtein Distance, or Edit Distance algorithm. To do\n" +
                "a fuzzy search use the tilde, \"~\", symbol at the end of a Single word Term.\n" +
                "An additional (optional) parameter can specify the required similarity. The value is between 0 and 1,\n" +
                "with a value closer to 1 only terms with a higher similarity will be matched. The default that is\n" +
                "used if the parameter is not given is 0.5.\n\n" +

                "\tProximity Searches\n" +
                "Lucene supports finding words are a within a specific distance away. To do a proximity search use\n" +
                "the tilde, \"~\", symbol at the end of a Phrase.\n\n" +

                "\tRange Searches\n" +
                "Range Queries allow one to match documents whose field(s) values are between the lower and upper\n" +
                "bound specified by the Range Query. Range Queries can be inclusive or exclusive of the upper and\n" +
                "lower bounds. Sorting is done lexicographically.\n" +

                "Inclusive range queries are denoted by square brackets. Exclusive range queries are denoted by" +
                "curly brackets.\n\n" +

                "\tBoosting a Term\n" +
                "Lucene provides the relevance level of matching documents based on the terms found. To boost a\n" +
                "term use the caret, \"^\", symbol with a boost factor (a number) at the end of the term you are\n" +
                "searching. The higher the boost factor, the more relevant the term will be.\n\n" +

                "\tBoolean Operators\n" +
                "Boolean operators allow terms to be combined through logic operators. Lucene supports AND, \"+\",\n" +
                "OR, NOT and \"-\" as Boolean operators(Note: Boolean operators must be ALL CAPS).\n\n" +

                "The OR operator is the default conjunction operator. This means that if there is no Boolean\n" +
                "operator between two terms, the OR operator is used. The OR operator links two terms and finds\n" +
                "a matching document if either of the terms exist in a document. This is equivalent to a union\n" +
                "using sets. The symbol || can be used in place of the word OR.\n\n" +

                "The AND operator matches documents where both terms exist anywhere in the text of a single\n" +
                "document. This is equivalent to an intersection using sets. The symbol && can be used in place\n" +
                "of the word AND.\n\n" +

                "The \"+\" or required operator requires that the term after the \"+\" symbol exist somewhere\n" +
                "in a the field of a single document.\n\n" +

                "The NOT operator excludes documents that contain the term after NOT. This is equivalent to a\n" +
                "difference using sets. The symbol ! can be used in place of the word NOT.\n\n" +

                "The \"-\" or prohibit operator excludes documents that contain the term after the \"-\" symbol.\n\n" +

                "\tGrouping\n" +
                "Lucene supports using parentheses to group clauses to form sub queries. This can be very useful\n" +
                "if you want to control the boolean logic for a query.\n\n" +

                "\tSpecial characters\n"+
                "Lucene supports escaping special characters that are part of the query syntax. The current list\n" +
                "special characters are: + - && || ! ( ) { } [ ] ^ \" ~ * ? : \n\n" +

                "To escape these character use the \\ before the character.\n"
            );
        } else {
            System.out.println("Options:");

            List<HelpItem> helpItems = new ArrayList<HelpItem>();
            helpItems.addAll(new DeleteCommand().getHelpItems());
            helpItems.addAll(new UpdateCommand().getHelpItems());
            helpItems.addAll(new RescanCommand().getHelpItems());
            helpItems.addAll(new ShowCommand().getHelpItems());
            helpItems.add(new HelpItem(null, null));
            helpItems.addAll(new FindCommand().getHelpItems());
            helpItems.add(new HelpItem(null, null));
            helpItems.addAll(new HelpCommand().getHelpItems());

            int maxCommandLength = 0;
            for (HelpItem helpItem : helpItems) {
                if (helpItem.getCommand() != null) {
                    maxCommandLength = Math.max(maxCommandLength, helpItem.getCommand().length());
                }
            }

            for (HelpItem item : helpItems) {
                if (item.getCommand() != null) {
                    System.out.print("\t" + String.format("%" + (-(maxCommandLength + 3)) + "s", item.getCommand())
                            + item.getDescription());
                }

                System.out.println();
            }
        }
    }

    @Override
    public List<HelpItem> getHelpItems() {
        List<HelpItem> helpItems = new ArrayList<HelpItem>();
        helpItems.add(new HelpItem(getName() + " --syntax", "display syntax description supported by FIDX"));
        return helpItems;
    }
}
